package io.zerous.zexgraph;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import io.zerous.zexgraph.math.Vector2;

/**
 * Created by Zerous on 2018/7/21.
 */
public class PlotView extends View {
    public interface Plot {
        float drawPlot(float x);
    }

    float ox = 0, oy = 0, v0 = 0;

    boolean isFirst = true;

    private Plot plot;
    private float pixelPerUnit = 0.005f;

    private Paint paint = new Paint();

    private Vector2 origin = new Vector2();

    public PlotView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        paint.setAntiAlias(true);
        //paint.setTextAlign(Paint.Align.CENTER);

    }

    public void reset() {
        isFirst = true;
    }

    public void setPlot(Plot plot) {
        this.plot = plot;

        invalidate();
    }

    public void setPixelPerUnit(float unit) {
        pixelPerUnit = unit;
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getPointerCount() == 1) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                ox = event.getX(0);
                oy = event.getY(0);
            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                origin.x += event.getX(0) - ox;
                origin.y += event.getY(0) - oy;
                ox = event.getX(0);
                oy = event.getY(0);
                invalidate();
            }
            return true;
        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();

        if (isFirst) {
            origin.x = getWidth()/2;
            origin.y = getHeight()/2;
            isFirst = false;
        }

        if (origin.y > 0 && origin.y < height)
            canvas.drawLine(0, origin.y, width, origin.y, paint);

        if (origin.x > 0 && origin.x < width)
            canvas.drawLine(origin.x, 0, origin.x, height, paint);

        if (plot != null) {
            float x0 = -origin.x;
            float y0 = origin.y - (plot.drawPlot(x0 * pixelPerUnit)/pixelPerUnit);
            float tx, ty;
            for (float x = 1;x <= width;x++) {
                tx = x - origin.x;
                ty = origin.y - (plot.drawPlot(tx * pixelPerUnit)/pixelPerUnit);

                if (ty > 0 || ty < height) {
                    canvas.drawLine((origin.x + x0), y0 , (origin.x + tx), ty, paint);
                }

                x0 = tx;
                y0 = ty;
            }
        }

        if (pixelPerUnit < 0.1f) {
            float size = paint.getTextSize();

            if (origin.y > 0 && origin.y < height) {
                for (float i = findStartX(); i < width; i += 1 / pixelPerUnit) {
                    canvas.drawLine(i, origin.y - 10, i, origin.y + 10, paint);
                    int n = (int) ((i - origin.x) * pixelPerUnit);
                    canvas.drawText(n + "", i + size / 2, origin.y + size, paint);
                }
            }

            if (origin.x > 0 && origin.x < width) {
                for (float i = findStartY(); i < height; i += 1 / pixelPerUnit) {
                    canvas.drawLine(origin.x - 10, i, origin.x + 10, i, paint);
                    int n = (int) ((origin.y - i) * pixelPerUnit);
                    if (n == 0) continue;
                    canvas.drawText(n + "", origin.x + size, i + size / 2, paint);
                }
            }
        }
    }

    private float findStartX() {
        return origin.x % (1/pixelPerUnit);
    }

    private float findStartY() {
        return origin.y % (1/pixelPerUnit);
    }
}
